﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
using SocialFront.Providers.Avatar;
using SocialFront.Providers.Member;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.relation;
using System.Web.Profile;

namespace SocialFront.Provider.Umbraco
{
    public class UmbracoMember : MemberBase
    {
        /// <summary>
        /// Creates the specified member.
        /// </summary>
        /// <param name="member">The member.</param>
        /// <returns></returns>
        public override Entities.Member Create(Entities.Member member)// string username, string password, string email, DateTime dob, bool isSubscribingToNewsletter)
        {
            return UpdateUmbracoMember(member);
        }

        /// <summary>
        /// Updates the umbraco member.
        /// </summary>
        /// <param name="member">The member.</param>
        /// <returns></returns>
        private Entities.Member UpdateUmbracoMember(Entities.Member member)
        {
            try
            {
                //MembershipUser umbMember = System.Web.Security.Membership.GetUser();
                MemberType communityMemberType = new MemberType(Convert.ToInt32(Config.sfMemberType));

                //Member updateMember;
                MembershipUser updateMember;
                if (member.Id == 0)
                {

                    // TODO: Use the MembershipProvider and ProfileProvider for this!
                    Member newMember = Member.MakeNew(member.LoginName, communityMemberType, new User(0));
                    
                    if (!string.IsNullOrEmpty(member.AboutMe))
                    {
                        newMember.getProperty("aboutMe").Value = member.AboutMe;
                    }
                    newMember.Email = member.Email;
                    newMember.Password = member.Password;
                    newMember.getProperty("newsletter").Value = member.Newsletter;
                    //newMember.getProperty("dateOfBirth").Value = member.DateOfBirth.ToString("yyyy-MM-dd");

                    // Add user to the Member Admin Group
                    newMember.AddGroup(MemberGroup.GetByName("sfMember").Id);
                    newMember.Save();

                    return ConvertTo(newMember);


                    //updateMember.Password = member.Password;
                    //updateMember = Membership.CreateUser(member.LoginName, member.Password, member.Email);
                }
                else
                {
                    updateMember = Membership.GetUser();
                    //updateMember = Member.GetCurrentMember();
                }

                updateMember.Email = member.Email;

                //MembershipUser mu2 = Membership.CreateUser();
                
                //MembershipUser mu = Membership.GetUser();
                //sfCommunityMember muprofile = (sfCommunityMember)ProfileBase.Create(mu.UserName, true);
                //muprofile.AboutMe = "hello";
                
                if (!string.IsNullOrEmpty(member.Password))
                {
                    //updateMember.Password = member.Password;
                    updateMember.ChangePassword(member.Password, updateMember.ResetPassword());
                }

                // Can't change the UserName for the MembershipUser
                //if (updateMember.UserName != member.LoginName)
                //{
                //    updateMember. = member.LoginName;
                //}


                // TODO: Use ProfileProvider to do this!
                //if (!string.IsNullOrEmpty(member.AboutMe))
                //{
                //    updateMember.getProperty("aboutMe").Value = member.AboutMe;
                //}
                //updateMember.getProperty("newsletter").Value = member.Newsletter;
                //updateMember.getProperty("dateOfBirth").Value = member.DateOfBirth.ToString("yyyy-MM-dd");

                //// Add user to the Member Admin Group
                //updateMember.AddGroup(MemberGroup.GetByName("sfMember").Id);
                //updateMember.Save();
                
                //string i = (string)Membership.GetUser().ProviderUserKey;
                //return ConvertTo(updateMember);
                return ConvertTo(updateMember);
            }
            catch (Exception ex)
            {
                Log.Add(LogTypes.Error, -1, ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Updates the member.
        /// </summary>
        /// <param name="member">The member.</param>
        /// <returns></returns>
        public override Entities.Member UpdateMember(Entities.Member member)
        {
            return UpdateUmbracoMember(member); 
        }

        /// <summary>
        /// Gets the member by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public override Entities.Member GetMemberById(int id)
        {
            //throw new NotImplementedException("GetMemberById has not been implemented");
            return ConvertTo(new Member(id));
        }


        /// <summary>
        /// Gets the member from email.
        /// </summary>
        /// <param name="email">The email.</param>
        /// <returns></returns>
        public override Entities.Member GetMemberFromEmail(string email)
        {
            //return ConvertTo(Member.GetMemberFromEmail(email));
            string username = Membership.GetUserNameByEmail(email);
            if (username == null)
            {
                return null;
            }
            return ConvertTo(Membership.GetUser(username));
        }

        /// <summary>
        /// Gets all members.
        /// </summary>
        /// <returns></returns>
        public override List<Entities.Member> GetAllMembers()
        {
            return GetAllMembers(null);
        }

        public override List<Entities.Member> GetAllMembers(int? pageSize)
        {
            return GetAllMembers(pageSize, null);
        }

        public override List<Entities.Member> GetAllMembers(int? pageSize, int? page)
        {
            int total;
            return GetAllMembers(pageSize, page, out total);
        }

        public override List<Entities.Member> GetAllMembers(int? pageSize, int? page, out int total)
        {
            //List<Entities.Member> members =  ConvertTo(Member.GetAll);
            List<Entities.Member> members = ConvertTo(Membership.GetAllUsers());
            if (pageSize.HasValue && page.HasValue)
                members = members.OrderByDescending(b => b.CreatedDate).Skip((page.Value - 1) * pageSize.Value).Take(pageSize.Value).ToList();
            else if (pageSize.HasValue)
                members = members.OrderByDescending(b => b.CreatedDate).Take(pageSize.Value).ToList();

            members = members.OrderByDescending(b => b.CreatedDate).ToList();

            total = members.Count;
            return members;
        }

        /// <summary>
        /// Logouts the current member.
        /// </summary>
        /// <returns></returns>
        public override void LogoutCurrentMember()
        {
            Member currentMember = Member.GetCurrentMember();
            if (currentMember != null)
            {
                Member.RemoveMemberFromCache(currentMember.Id);
                Member.ClearMemberFromClient(currentMember.Id);
            }
        }

        /// <summary>
        /// Gets the current member.
        /// </summary>
        /// <returns></returns>
        public override Entities.Member GetCurrentMember()
        {
            return (ConvertTo(Member.GetCurrentMember()));
            // TODO Use membership provider properly here
            //return (ConvertTo(Membership.GetUser()));
        }

        public override void ChangePassword()
        {
            throw new NotImplementedException();
        }

        public static Entities.Member ConvertTo(Member member)
        {
            if (member == null)
            {
                return null;
            }

            Entities.Member sfMember = new Entities.Member();

            sfMember.Id = member.Id;
            sfMember.CreatedDate = member.CreateDateTime;

            // Note: using the createdatetime here
            sfMember.ModifiedDate = member.CreateDateTime;

            sfMember.LoginName = member.LoginName;
            sfMember.Email = member.Email;
            //sfMember.Password = member.Password;

            // TODO: Use Profile Provider for this
            //if (member.getProperty("aboutMe") != null)
            //    sfMember.AboutMe = member.getProperty("aboutMe").Value.ToString();
            //DateTime dob;
            //if (member.getProperty("dateOfBirth") != null)
            //{
            //    if (DateTime.TryParse(member.getProperty("dateOfBirth").Value.ToString(), out dob))
            //        sfMember.DateOfBirth = dob;
            //}

            // Check the relations table to find the members area node - may not exist if we're creating a new user
            Relation[] relations = Relation.GetRelations(member.Id,
                                                         RelationType.GetByAlias("relateMemberToMemberDocType"));
            if (relations.Length > 0)
            {
                sfMember.MemberUrl = umbraco.library.NiceUrl(relations[0].Child.Id);
            }

            sfMember.Avatar = AvatarProvider.Provider.GetAvatar(sfMember);

            return sfMember;
        }

        /// <summary>
        /// Converts to.
        /// </summary>
        /// <param name="member">The member.</param>
        /// <returns></returns>
        public static Entities.Member ConvertTo(MembershipUser member)
        {
            if (member == null)
            {
                return null;
            }

            Entities.Member sfMember = new Entities.Member();

            sfMember.Id = (int)member.ProviderUserKey;
            sfMember.CreatedDate = member.CreationDate;

            // Note: the modified date may not be the last activity date - what's this for anyway?
            sfMember.ModifiedDate = member.LastActivityDate;

            sfMember.LoginName = member.UserName;
            sfMember.Email = member.Email;
            //sfMember.Password = member.Password;

            // TODO: Use Profile Provider for this
            //if (member.getProperty("aboutMe") != null)
            //    sfMember.AboutMe = member.getProperty("aboutMe").Value.ToString();
            //DateTime dob;
            //if (member.getProperty("dateOfBirth") != null)
            //{
            //    if (DateTime.TryParse(member.getProperty("dateOfBirth").Value.ToString(), out dob))
            //        sfMember.DateOfBirth = dob;
            //}

            // Check the relations table to find the members area node - may not exist if we're creating a new user
            Relation[] relations = Relation.GetRelations((int)member.ProviderUserKey,
                                                         RelationType.GetByAlias("relateMemberToMemberDocType"));
            if (relations.Length > 0)
            {
                sfMember.MemberUrl = umbraco.library.NiceUrl(relations[0].Child.Id);
            }

            sfMember.Avatar = AvatarProvider.Provider.GetAvatar(sfMember);

            return sfMember;
        }

        /// <summary>
        /// Converts to.
        /// </summary>
        /// <param name="members">The members.</param>
        /// <returns></returns>
        public static List<Entities.Member> ConvertTo(MembershipUserCollection members)
        {
            List<Entities.Member> sfMembers = new List<Entities.Member>();
            foreach (MembershipUser member in members)
            {
                sfMembers.Add(ConvertTo(member));
            }

            return sfMembers;
        }

        /// <summary>
        /// Converts to.
        /// </summary>
        /// <param name="sfMember">The member.</param>
        /// <returns></returns>
        //public static Member ConvertTo(Entities.Member sfMember)
        //{
        //    return Member.GetMemberFromEmail(sfMember.Email);
        //}

        public static MembershipUser ConvertTo(Entities.Member sfMember)
        {
            return Membership.GetUser(sfMember.Id);
        }

        /// <summary>
        /// Logins the member.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        public override Entities.Member LoginMember(string username, string password)
        {
            
            //Member m = Member.GetMemberFromLoginNameAndPassword(username, password);
            //if (m != null)
            //{
            //    Member.AddMemberToCache(m);
            //    //Member.AddMemberToCache(entMember, true, new TimeSpan(0, 15, 0));
            //    return ConvertTo(m);
            //}

            FormsAuthentication.SetAuthCookie(username, false);

            return null;     
        }

        /// <summary>
        /// Logins the member.
        /// </summary>
        /// <param name="sfMember">The member.</param>
        /// <returns></returns>
        public override Entities.Member LoginMember(Entities.Member sfMember)
        {
            MembershipUser m = ConvertTo(sfMember);
            FormsAuthentication.SetAuthCookie(m.UserName, false);
            
            //Member m = ConvertTo(sfMember);
            //// TODO: Make the amount of time the user is added to the cache for configurable for the system
            //Member.AddMemberToCache(mu);
            ////Member.AddMemberToCache(entMember, true, new TimeSpan(0, 15, 0));
            
            return sfMember;
        }
    }
}